﻿using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using System.Security.Cryptography;
using System.Text;
using Pumpkin.Utils;

namespace Pumpkin.FrameBase
{
    public static class FileHelper
    {
        /// <summary>
        /// 当前编辑器工程所在目录
        /// </summary>
        public static string EditorProjectDir
        {
            get
            {
                return Application.dataPath.Substring(0, Application.dataPath.LastIndexOf("/Assets"));
            }
        }

        private static char[] combNameSperator = new char[] { '~', '!' };
        private static char[] pathSperator = new char[] { '/' };

        public static string CombNameToABPath(string name)
        {
            return name.Replace('~', '/');
        }

        public static string ABPathToCombName(string path)
        {
            return path.Replace('/', '~');
        }

        //由资源名查找对应bundle
        public static string GetABPath(string fileName)
        {
            return null;
        }

        //获取bundle目录下资源相对路径
        public static string GetABResPath(string fileName)
        {
            return "Assets/" + HotFixConfigs.BundleRootDir + "/" + fileName;
        }

        //获取bundle目录下资源绝对路径
        public static string GetABResFullPath(string fileName)
        {
            return CombinePath(EditorProjectDir, GetABResPath(fileName));
        }

        public static string GetPersisitentPath()
        {
            return FileUtil.ins.GetPersisitentPath();
        }

        /// <summary>
        /// 把2个路径合并
        /// </summary>
        public static string CombinePath(string path1, string path2)
        {
            var path = Path.Combine(path1, path2);
            return FormatFilePath(path);
        }

        /// <summary>
        /// 格式化文件目录为统一格式
        /// </summary>
        public static string FormatFilePath(string filePath)
        {
            var path = filePath.Replace('\\', '/');
            path = path.Replace("//", "/");
            return path;
        }

        public static bool FileExist(string filePath)
        {
            return File.Exists(filePath);
        }

        public static void DeleteFile(string filepath)
        {
            File.Delete(filepath);
        }

        public static string FileReadAllText(string filepath)
        {
            if (File.Exists(filepath))
                return File.ReadAllText(filepath);
            return
                null;
        }

        public static byte[] FileReadAllBytes(string filepath)
        {
            if (File.Exists(filepath))
                return File.ReadAllBytes(filepath);
            else
                return null;
        }

        public static void FileWriteAllText(string filepath, string text, bool checkcDir = true)
        {
            if (checkcDir)
            {
                CreateDirectoryByFile(filepath);
            }
            File.WriteAllText(filepath, text);
        }

        public static void FileWriteAllBytes(string filepath, byte[] bytes, bool checkDir = true)
        {
            if (checkDir)
            {
                CreateDirectoryByFile(filepath);
            }
            File.WriteAllBytes(filepath, bytes);
        }

        public static void CreateDirectory(string dir)
        {
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);
        }

        public static void CreateDirectoryByFile(string filepath)
        {
            CreateDirectory(Path.GetDirectoryName(filepath));
        }

        public static bool IsBundlePath(string path)
        {
            return path.StartsWith("Assets/" + HotFixConfigs.BundleRootDir);
        }

        public static void Recursive(string path, List<string> files, List<string> paths)
        {
            string[] names = Directory.GetFiles(path);
            string[] dirs = Directory.GetDirectories(path);
            foreach (string filename in names)
            {
                string ext = Path.GetExtension(filename);
                if (ext.Equals(".meta")) continue;
                if (filename.Contains(".DS_Store")) continue;
                if (filename.Contains(".idea"))
                    continue;
                files.Add(filename.Replace('\\', '/'));
            }
            foreach (string dir in dirs)
            {
                if (!dir.EndsWith(".svn") && !dir.EndsWith(".idea"))
                {
                    paths.Add(dir.Replace('\\', '/'));
                    Recursive(dir, files, paths);
                }
            }
        }

        public static string GetMD5(string filePath)
        {
            try
            {
                return FileUtil.ins.GetMD5(filePath);
            }
            catch (Exception e)
            {
                Debug.LogError(filePath + ":cant read file");
                Debug.LogError(e.Message);
                return null;
            }
        }

        public static long GetFileSize(string filePath)
        {
            return new FileInfo(filePath).Length;
        }

        public static string GetExtensions(string fileName)
        {
            return Path.GetExtension(fileName);
        }
    }

    public abstract class FileUtil
    {
        public static FileUtil ins
        {
            get
            {
                if (ins_ == null)
                {
                    ins_ = CreateFileUtil();
                }

                return ins_;
            }
        }
        private static FileUtil ins_;
        private static FileUtil CreateFileUtil()
        {
            if (Application.platform == RuntimePlatform.WindowsEditor
            || Application.platform == RuntimePlatform.OSXEditor
            || Application.platform == RuntimePlatform.LinuxEditor)
            {
                return new FileUtilEditor();
            }

            if (Application.platform == RuntimePlatform.IPhonePlayer)
            {
                return new FileUtilIos();
            }

            if (Application.platform == RuntimePlatform.Android)
            {
                return new FileUtilAndroid();
            }

            Log.LogError("platform : " + Application.platform + "not supported");
            return new FileUtilUnknown();
        }
        public abstract string GetPersisitentPath();

        public virtual string GetMD5(string filePath)
        {
            var bytes = FileHelper.FileReadAllBytes(filePath);
            byte[] hash = null;
            using (var l_md5 = new MD5CryptoServiceProvider())
            {
                hash = l_md5.ComputeHash(bytes);
            }
            var sb = new StringBuilder();
            foreach (var b in hash)
                sb.Append(b.ToString("x2"));
            return sb.ToString();
        }
    }

    public class FileUtilAndroid : FileUtil
    {
        public override string GetPersisitentPath()
        {
            return Application.persistentDataPath;
        }

        public override string GetMD5(string filePath)
        {
            var bytes = FileHelper.FileReadAllBytes(filePath);
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            byte[] md5Data = md5.ComputeHash(bytes);
            md5.Clear();

            string destString = "";
            for (int i = 0; i < md5Data.Length; i++)
            {
                destString += System.Convert.ToString(md5Data[i], 16).PadLeft(2, '0');
            }
            destString = destString.PadLeft(32, '0');
            return destString;
        }
    }

    public class FileUtilIos : FileUtil
    {
        public override string GetPersisitentPath()
        {
            int length = Application.persistentDataPath.Length;
            return Application.persistentDataPath.Substring(0, length - 10) + "/Library/Caches/";
        }
    }

    public class FileUtilEditor : FileUtil
    {
        private string persistentPath = "EditorDownLoadedBundles";
        public override string GetPersisitentPath()
        {
            var path = FileHelper.CombinePath(FileHelper.EditorProjectDir, persistentPath);
            FileHelper.CreateDirectory(path);
            return path;
        }
    }

    public class FileUtilUnknown : FileUtil
    {
        public FileUtilUnknown()
        {
            throw new NotImplementedException("unknown platform");
        }
        public override string GetPersisitentPath()
        {
            return "";
        }
    }
}

